package com.light.gamecomponents.physics;
import org.anddev.andengine.entity.primitive.Rectangle;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.extension.physics.box2d.PhysicsConnector;
import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
import org.anddev.andengine.extension.physics.box2d.PhysicsWorld;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.joints.FrictionJointDef;
import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;
import com.light.gamecomponents.gravitylight.GravityLight;
import com.light.roller.Direction;
import com.light.roller.ResourceManager;
import com.light.roller.Roller;

public class MovingBar extends PhysicsComponents{

	private final Vector2 m_fixPosition;
	private final String m_resourceName;
	private final Direction m_direction;
	
	protected FixChainPart fixBeginPart = null;
	
	public MovingBar(Roller game, String resourceName, Vector2 fixPosition, Vector2 size) 
	{
		super(game, resourceName, new Vector2(fixPosition), size);
		m_resourceName = resourceName;
		m_fixPosition = fixPosition;
		m_direction=Direction.RIGHT;
		
	}
	
	public MovingBar(Roller game, String resourceName, Vector2 fixPosition, Vector2 size , Direction direction) 
	{
		super(game, resourceName, new Vector2(fixPosition), size);
		
		
		m_resourceName = resourceName;
		m_fixPosition = fixPosition;
		m_direction=direction;				

	}
	
	private void initFixPoint(Scene scene,PhysicsWorld physicsWorld)
	{
		FixtureDef tempFixtureDef = PhysicsFactory.createFixtureDef(20, 0.0f, 0.0f);
		tempFixtureDef.filter.categoryBits = Roller.CATEGORYBIT_BAR;
		tempFixtureDef.filter.maskBits = Roller.MASKBIT_BAR;
		Vector2 fixPoint = new Vector2(m_fixPosition);
		
		switch(m_direction)
		{
			case RIGHT:
				fixPoint.x += 4;
				fixPoint.y += 11;
				break;
			case LEFT:
				m_sprite.getTextureRegion().setFlippedHorizontal(true);
				fixPoint.x +=m_sprite.getWidth()-4;
				fixPoint.y += 11;
				break;
			case DOWN:
				fixPoint.x += 11;
				fixPoint.y += 4;
				break;
			case UP:
				m_sprite.getTextureRegion().setFlippedVertical(true);
				fixPoint.x += 4;
				fixPoint.y += m_sprite.getHeight()-4;
				break;
		}		
		
		fixBeginPart = new FixChainPart(new Rectangle(fixPoint.x,fixPoint.y,2,2),m_resourceName,tempFixtureDef);
		fixBeginPart.onLoadScene(scene, physicsWorld);
	}
	
	@Override
	public void onUpdate(float pSecondsElapsed) {
	}

	@Override
	public void reset() {
			
	}

	@Override
	public void onLoadResources() {
		ResourceManager.onLoadResources(m_resourceName, m_game);
		m_textureRegion = ResourceManager.getTextureRegion(m_resourceName);
	}
		
	@Override
	public void unLoadResources() {
		m_textureRegion = null;
		ResourceManager.unLoadResources(m_resourceName, m_game);
	}

	@Override
	public void onLoadScene(Scene scene, PhysicsWorld physicsWorld) {
		FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(20, 0.0f, 0.2f);
			
		objectFixtureDef.filter.categoryBits = Roller.CATEGORYBIT_BAR;
		objectFixtureDef.filter.maskBits = Roller.MASKBIT_BAR;
		

		
		m_sprite = new Sprite(m_initialPosition.x, 
				  		      m_initialPosition.y,
                              m_textureRegion);
			
		m_body = PhysicsFactory.createBoxBody(physicsWorld, 
											  m_sprite, 
											  BodyType.StaticBody, 
											  objectFixtureDef);
		
		
		initFixPoint(scene, physicsWorld);		
			
		scene.attachChild(m_sprite);
		m_physicsConnector = new PhysicsConnector(m_sprite, m_body, true, true);
		physicsWorld.registerPhysicsConnector(m_physicsConnector);
		
		RevoluteJointDef jd = new RevoluteJointDef();

		jd.collideConnected = false;
		jd.initialize(m_body,fixBeginPart.getBody(), fixBeginPart.getBody().getPosition());
		physicsWorld.createJoint(jd);
		getSprite().setColor(0.5f, 0.5f, 0.5f);
		//this.stopBody();

		}
		
	@Override
	public void removeFromScene(Scene scene, PhysicsWorld physicsWorld) 
	{
		physicsWorld.unregisterPhysicsConnector(m_physicsConnector);
		scene.detachChild(m_sprite);
		physicsWorld.destroyBody(m_body);
			
			//m_physicsConnector = null;
			//m_sprite = null;
			//m_body = null;
	}

	@Override
	public void onLoadEngine() {
			
	}

	@Override
	public void setPosition(int x, int y) {
			// TODO Auto-generated method stub
			
	}
	@Override
	public void rotate(float angle) {
		// TODO Auto-generated method stub
		
	}
	
	public Direction getDirection() { return m_direction; }
	
	@Override
	public Vector2 getSpritePosition() 
	{ 
		float barAngle = getSprite().getRotation();
		barAngle = barAngle / 180 * 3.14159f;
		double x = 0;
		double y = 0;
		switch (getDirection())
		{
		case RIGHT:
			x = m_sprite.getInitialX() + m_sprite.getWidth() / 2 * Math.cos(barAngle);
			y = m_sprite.getInitialY() + m_sprite.getWidth() / 2 * Math.sin(barAngle);
			break;
		case LEFT:
			barAngle = barAngle + 3.14159f;
			x = m_sprite.getInitialX() + m_sprite.getWidth() + m_sprite.getWidth() / 2 * Math.cos(barAngle);
			y = m_sprite.getInitialY() + m_sprite.getWidth() / 2 * Math.sin(barAngle);
			break;
		case UP:
			barAngle = barAngle - 3.14159f / 2;
			x = m_sprite.getInitialX()  + m_sprite.getHeight() / 2 * Math.cos(barAngle);
			y = m_sprite.getInitialY() + m_sprite.getHeight()  + m_sprite.getHeight() / 2 * Math.sin(barAngle);
			break;
		case DOWN:
			barAngle = barAngle + 3.14159f / 2;
			x = m_sprite.getInitialX()  + m_sprite.getHeight() / 2 * Math.cos(barAngle);
			y = m_sprite.getInitialY() + m_sprite.getHeight() / 2 * Math.sin(barAngle);
			break;
		}

 		return new Vector2((float)x, (float)y); 
	}


	@Override
	public boolean isInLight(GravityLight light)
	{

			float barAngle = getSprite().getRotation();
			barAngle = barAngle / 180 * 3.14159f;
			
			switch (getDirection())
			{
			case RIGHT:
				break;
			case LEFT:
				barAngle = barAngle + 3.14159f;
				break;
			case UP:
				barAngle = barAngle - 3.14159f / 2;
				break;
			case DOWN:
				barAngle = barAngle + 3.14159f / 2;
				break;
			}
			
			Vector2 disVec = new Vector2(getSpritePosition().x - light.getSpritePosition().x, 
					 					 getSpritePosition().y - light.getSpritePosition().y);
			float dis = (float)Math.sqrt(disVec.x * disVec.x + disVec.y * disVec.y);
			float angle = (float)Math.atan(disVec.y / disVec.x);
			if (disVec.y < 0)
			{
				if (angle <= 0)
					angle = 3.14f / 2 + (3.14f / 2 + angle);
			}
			else
			{
				if (angle > 0)
					angle = 3.14f + angle;
				else
					angle = 3.14f * 3 / 2 + (3.14f / 2 + angle);
			}
			
			if (barAngle >= 0)
				barAngle = barAngle % 6.28f;
			else
				barAngle = 6.28f + barAngle % 6.28f;
			
			
			float length = 0;
			switch (getDirection())
			{
			case RIGHT:
			case LEFT:
				length = getSprite().getWidth() / 2 * (float)Math.cos(barAngle - angle);
				break;
			case UP:
			case DOWN:
				length = getSprite().getHeight() / 2 * (float)Math.cos(barAngle - angle);
				break;
			}
			
			if (dis - 75 <= Math.abs(length))
			{
				if (Math.abs(dis * (float)Math.sin(barAngle - angle)) < 90)
					return true;
				else 
					return false;
			}
			else
				return false;
		
	}

}


